#ifndef __M_HOST_H__
#define __M_HOST_H__
#include "mq_exchange.hpp"
#include "mq_queue.hpp"
#include "mq_binding.hpp"
#include "mq_message.hpp"

namespace qqmq {

    // VirtualHost 类表示一个虚拟主机，管理交换机、队列、绑定和消息等资源
    class VirtualHost {
        public:
            using ptr = std::shared_ptr<VirtualHost>;

            // 构造函数，初始化虚拟主机
            // hname: 虚拟主机的名称
            // basedir: 消息存储的基础目录
            // dbfile: 数据库文件的路径
            VirtualHost(const std::string &hname, const std::string &basedir, const std::string &dbfile):
                _host_name(hname),
                // 创建交换机管理器
                _emp(std::make_shared<ExchangeManager>(dbfile)),
                // 创建消息队列管理器
                _mqmp(std::make_shared<MsgQueueManager>(dbfile)),
                // 创建绑定管理器
                _bmp(std::make_shared<BindingManager>(dbfile)),
                // 创建消息管理器
                _mmp(std::make_shared<MessageManager>(basedir)) {
                // 获取到所有的队列信息，通过队列名称恢复历史消息数据
                QueueMap qm = _mqmp->allQueues();
                for (auto &q : qm) {
                    // 初始化队列的消息句柄，恢复历史消息
                    _mmp->initQueueMessage(q.first);
                }
            }

            // 声明一个交换机
            // name: 交换机的名称
            // type: 交换机的类型
            // durable: 交换机是否持久化
            // auto_delete: 交换机是否自动删除
            // args: 交换机的额外参数
            bool declareExchange(const std::string &name,
                ExchangeType type, bool durable, bool auto_delete,
                const google::protobuf::Map<std::string, std::string> &args) {
                
                return _emp->declareExchange(name, type, durable, auto_delete, args);
            }

            // 删除一个交换机
            // name: 要删除的交换机的名称
            void deleteExchange(const std::string &name) {
                // 删除交换机的时候，需要将交换机相关的绑定信息也删除掉。
                _bmp->removeExchangeBindings(name);
                return _emp->deleteExchange(name);
            }

            // 检查一个交换机是否存在
            // name: 要检查的交换机的名称
            bool existsExchange(const std::string &name) {
                return _emp->exists(name);
            }

            // 根据名称选择一个交换机
            // ename: 要选择的交换机的名称
            Exchange::ptr selectExchange(const std::string &ename) {
                return _emp->selectExchange(ename);
            }

            // 声明一个队列
            // qname: 队列的名称
            // qdurable: 队列是否持久化
            // qexclusive: 队列是否排他
            // qauto_delete: 队列是否自动删除
            // qargs: 队列的额外参数
            bool declareQueue(const std::string &qname, 
                bool qdurable, 
                bool qexclusive,
                bool qauto_delete,
                const google::protobuf::Map<std::string, std::string> &qargs) {
                // 初始化队列的消息句柄（消息的存储管理）
                _mmp->initQueueMessage(qname);
                // 队列的创建
                return _mqmp->declareQueue(qname, qdurable, qexclusive, qauto_delete, qargs);
            }

            // 删除一个队列
            // name: 要删除的队列的名称
            void deleteQueue(const std::string &name) {
                // 删除的时候队列相关的数据有两个：队列的消息，队列的绑定信息
                // 销毁队列的消息管理
                _mmp->destroyQueueMessage(name);
                // 移除队列的绑定信息
                _bmp->removeMsgQueueBindings(name);
                return _mqmp->deleteQueue(name);
            }

            // 检查一个队列是否存在
            // name: 要检查的队列的名称
            bool existsQueue(const std::string &name) {
                return _mqmp->exists(name);
            }

            // 获取所有队列的信息
            QueueMap allQueues() {
                return _mqmp->allQueues();
            }

            // 将队列绑定到交换机
            // ename: 交换机的名称
            // qname: 队列的名称
            // key: 绑定键
            bool bind(const std::string &ename, const std::string &qname, const std::string &key) {
                // 选择交换机
                Exchange::ptr ep = _emp->selectExchange(ename);
                if (ep.get() == nullptr) {
                    // 若交换机不存在，记录日志并返回失败
                    DLOG("进行队列绑定失败，交换机%s不存在！", ename.c_str());
                    return false;
                }
                // 选择队列
                MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
                if (mqp.get() == nullptr) {
                    // 若队列不存在，记录日志并返回失败
                    DLOG("进行队列绑定失败，队列%s不存在！", qname.c_str());
                    return false;
                }
                // 执行绑定操作，根据交换机和队列的持久化情况设置绑定的持久化属性
                return _bmp->bind(ename, qname, key, ep->durable && mqp->durable);
            }

            // 解除队列与交换机的绑定
            // ename: 交换机的名称
            // qname: 队列的名称
            void unBind(const std::string &ename, const std::string &qname) {
                return _bmp->unBind(ename, qname);
            }

            // 获取交换机的所有绑定信息
            // ename: 交换机的名称
            MsgQueueBindingMap exchangeBindings(const std::string &ename) {
                return _bmp->getExchangeBindings(ename);
            }

            // 检查交换机和队列之间的绑定是否存在
            // ename: 交换机的名称
            // qname: 队列的名称
            bool existsBinding(const std::string &ename, const std::string &qname) {
                return _bmp->exists(ename, qname);
            }

            // 向指定队列发布消息
            // qname: 队列的名称
            // bp: 消息的基本属性
            // body: 消息的内容
            bool basicPublish(const std::string &qname, BasicProperties *bp, const std::string &body) {
                // 选择队列
                MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
                if (mqp.get() == nullptr) {
                    // 若队列不存在，记录日志并返回失败
                    DLOG("发布消息失败，队列%s不存在！", qname.c_str());
                    return false;
                }
                // 插入消息到队列
                return _mmp->insert(qname, bp, body, mqp->durable);
            }

            // 从指定队列消费消息
            // qname: 队列的名称
            MessagePtr basicConsume(const std::string &qname) {
                return _mmp->front(qname);
            }

            // 确认指定队列中的消息处理完成
            // qname: 队列的名称
            // msgid: 消息的 ID
            void basicAck(const std::string &qname, const std::string &msgid) {
                return _mmp->ack(qname, msgid);
            }

            // 清空虚拟主机中的所有资源，包括交换机、队列、绑定和消息
            void clear() {
                _emp->clear();
                _mqmp->clear();
                _bmp->clear();
                _mmp->clear();
            }

        private:
            std::string _host_name; // 虚拟主机的名称
            ExchangeManager::ptr _emp; // 交换机管理器
            MsgQueueManager::ptr _mqmp; // 消息队列管理器
            BindingManager::ptr _bmp; // 绑定管理器
            MessageManager::ptr _mmp; // 消息管理器
    };
}

#endif